home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 051-075 / disk_073 / lit / lit.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  9KB  |  376 lines

  1. #include <stdio.h>
  2. #include <exec/types.h>
  3.  
  4. /*
  5. * Lit Text Utility -  Filter a file to stdout showing all characters in
  6. * an unambiguous format. See Lit Text Utility Manual for specification.
  7. *
  8. * Version 2.0 - 11/16/86, Copyright (C) 1986 Donald J Irving
  9. *
  10. * Author:    Donald J. Irving
  11. *            9812 Gardenwood Way
  12. *            Sacramento, CA 96827
  13. *            (916) 366-3225
  14. *            CIS:   73547,1335
  15. *            PLINK: ops158
  16. *
  17. * Lit  may be freely distributed for personal use.
  18. * Lit may not be sold or placed on a disk offered for sale without written
  19. * permission from the author. Written permission will normally be granted
  20. * at no charge for inclusion on so called "public domain disks" which are
  21. * sold for nominal medium and handling fees. Lit may be modified for 
  22. * personal use, and trivial modifications such as changing defaults or
  23. * specifying include files may be made for distribution, but lit is not to
  24. * be modified substantially for distribution without written consent of the
  25. * author. The lit.c source, lit manual file , and this copyright notice must 
  26. * be included on all distributions.
  27. * Here is the overall algorithm, minus some of the details:
  28. *
  29. *    if unable to interpret command line arguments
  30. *        print an error message and a Usage line;
  31. *    else
  32. *        set options and open files;
  33. *        if line specified to start on is not the first line
  34. *            throw out input file lines until the line specified;
  35. *        while read next char from input file
  36. *            if the char is printable
  37. *                print it;
  38. *            else
  39. *                represent it in a special format;
  40. *            if the char is a line feed
  41. *                output a linefeed;
  42. *                if there was a number of lines to print specified
  43. *                and ++line count equals that number
  44. *                    return;
  45. * Functions not returning values are not typed. Functions returning values
  46. * are explicitly typed.
  47. *  
  48. */
  49.  
  50. /* The four possible settings for representation mode. */
  51. #define BSLASH        1        /* use backslash rep else numeric */
  52. #define CONTROL        2        /* use control char reps else numeric */
  53. #define ALLREPS        3        /* use backslash else control else numeric */
  54. #define NUMERIC        4        /* use numeric value reps only */
  55.  
  56. /* The three possible settings for  numeric number base */
  57. #define OCT               1        /* use octal representations as in \033 */
  58. #define HEX            2        /* use hex representations as in \1B */
  59. #define DEC            3        /* use decimal representations as in \027 */
  60.  
  61. /* The most likely setting for how many lines to print */
  62. #define ALL_LINES    32767    /* print all the lines in the file */
  63.  
  64. /*
  65. * Here are the default option settings. If you don't like them, please
  66. * change them here. The comments on the define lines show the the default
  67. * settings chosen by the author and upon which the manual is based. Please
  68. * leave the comments as they are.
  69. */
  70.                                                     /* original        */
  71. #define DEFAULT_START        1                        /* 1            */
  72. #define DEFAULT_PRINT        ALL_LINES                /* ALL_LINES    */
  73. #define DEFAULT_OUTMODE     BSLASH                    /* BSLASH        */
  74. #define DEFAULT_BASE        OCT                        /* OCT            */
  75.  
  76. /* Non-printing characters which require special handling in the code */
  77. #define DEL        '\177'
  78.  
  79. struct opt {
  80.     short start;
  81.     short print;
  82.     short outmode;
  83.     short base;
  84. };
  85.  
  86. typedef struct opt opt_t;
  87.  
  88. main(argc, argv)  
  89. int argc;  
  90. char *argv[];  
  91. {
  92.     FILE *ifp = NULL;
  93.     register short c;
  94.     static opt_t opt = {
  95.         DEFAULT_START,
  96.         DEFAULT_PRINT,
  97.         DEFAULT_OUTMODE,
  98.         DEFAULT_BASE
  99.     };
  100.  
  101.     if (! process_args(argc, argv, &ifp, &opt))
  102.         printf("Usage: lit [<filename>] [-s<n>] [-p<n>] [-[bcan][ohd]]\n");
  103.     else {
  104.         if (opt.start != 1  && ! find_start_line(ifp, opt.start))
  105.             return;
  106.         while ((c = getc(ifp)) != EOF) {
  107.             if (! print_char(c, opt.outmode))
  108.                 represent_char(c, opt.outmode, opt.base);
  109.             if (c == '\n') {
  110.                 putchar('\n');
  111.                 if (opt.print != ALL_LINES &&  last_line(opt.print))
  112.                     break;
  113.             }
  114.         }
  115.         if (c != '\n')
  116.             putchar('\n');
  117.     }
  118. }
  119.  
  120.  
  121. /*
  122. * process_args -- Process all the command line arguments. Each argument is
  123. * expected to be either a minus sign option or an input file name. If an
  124. * input file is already open, a subsequent input file name argument is an
  125. * error.
  126. */
  127.  
  128. BOOL process_args(argc, argv, ifp, opt)
  129. int argc;
  130. char *argv[];
  131. FILE **ifp;
  132. opt_t *opt;
  133. {
  134.     register short i;
  135.  
  136.     for (i = 1; i < argc; i++) {
  137.         if (*argv[i] == '-') {
  138.             if (! process_opt(argv[i]+1, opt))
  139.                 return (FALSE);
  140.         }
  141.         else if (*ifp != NULL) {
  142.             printf("Invalid argument  %s, Input file already specified\n", 
  143.             argv[i]);
  144.             return (FALSE);
  145.         }
  146.         else if ((*ifp = fopen(argv[i], "r")) == NULL) {
  147.             printf("Unable to open input file %s\n", argv[i]);
  148.             return (FALSE);
  149.         }
  150.     }
  151.  
  152.     if (*ifp == NULL)
  153.         *ifp = stdin;
  154.     return (TRUE);
  155. }
  156.  
  157.  
  158. /*
  159. * process_opt -- Process a minus-sign command line argument. The options
  160. * s<linenum> and p<numlines> must stand alone with their own minus signs; 
  161. * The options b,c,a,n,o,h,d may be stacked after a single minus sign.
  162. */
  163.  
  164. BOOL process_opt(arg, opt)
  165. char *arg;
  166. opt_t *opt;
  167. {
  168.     switch (*arg) {
  169.     case 's':
  170.         opt->start = atoi(arg+1);            /* set starting linenum */
  171.         break;
  172.     case 'p':
  173.         opt->print = atoi(arg+1);            /* set linenums to print */
  174.         break;
  175.     default:
  176.         for (; *arg; arg++) {
  177.             switch (*arg) {
  178.             case 'b':
  179.                 opt->outmode = BSLASH;        /* use backslash rep else */
  180.                 break;                        /* numeric rep              */
  181.             case 'c':
  182.                 opt->outmode = CONTROL;        /* use control char rep   */
  183.                 break;                        /* else numeric rep       */
  184.             case 'a':
  185.                 opt->outmode = ALLREPS;        /* use backslash else     */
  186.                 break;                        /* control else numeric   */
  187.             case 'n':
  188.                 opt->outmode = NUMERIC;        /* use numeric rep only   */
  189.                 break;
  190.             case 'o':
  191.                 opt->base = OCT;        /* numeric rep base is octal */
  192.                 break;
  193.             case 'h':
  194.                 opt->base = HEX;        /* numeric rep base is hex */
  195.                 break;
  196.             case 'd':
  197.                 opt->base = DEC;        /* numeric rep base is decimal */
  198.                 break;
  199.             default:
  200.                 printf("Unknown option: %c\n", *arg);
  201.                 return (FALSE);
  202.             }
  203.         }
  204.     }
  205.     return (TRUE);
  206. }
  207.  
  208.  
  209. /*
  210. * find_start_line -- Find the first line to start printing on, throwing
  211. * out all the lines along the way.
  212. */
  213.  
  214. BOOL find_start_line(ifp, start)
  215. FILE *ifp;
  216. short start;
  217. {
  218.     register short c, lineno = 1;
  219.  
  220.     while (lineno < start) {
  221.         while ((c = getc(ifp)) != EOF  &&  c != '\n')
  222.             ;
  223.         if (c == EOF)
  224.             return (FALSE);
  225.         lineno++;
  226.     }
  227.     return (TRUE);
  228. }
  229.  
  230.  
  231. /*
  232. * last_line -- Return true if the line just printed was the last line
  233. * to print.
  234. */
  235.  
  236. BOOL last_line(print)
  237. short print;
  238. {
  239.     static short printed = 0;
  240.  
  241.     if (++printed == print)
  242.         return (TRUE);
  243.     return (FALSE);
  244. }
  245.  
  246.  
  247. /*
  248. * print_char -- Print a printable character. If it's a \, or if
  249. * it's a ^ and control codes are enabled, then preface it with a \.
  250. */
  251.  
  252. BOOL print_char(c, outmode) 
  253. short c, outmode;
  254. {
  255.     if (c < ' ' || c > '~')
  256.         return (FALSE);
  257.  
  258.     if (c == '\\'
  259.     || (c == '^' && (outmode == CONTROL || outmode == ALLREPS)))
  260.         putchar('\\');
  261.  
  262.     putchar(c);
  263.     return (TRUE);
  264. }
  265.  
  266.  
  267. /*
  268. * represent_char -- Represent a non-printable character using whichever
  269. * representation format is appropriate for the outmode selected. The
  270. * rep_xxx functions called try to represent the char in a particular
  271. * format, and return false if the the character is not applicable.
  272. */
  273.  
  274. represent_char(c, outmode, base)
  275. short c, outmode, base;
  276. {
  277.     switch (outmode) {
  278.     case BSLASH:
  279.         if (rep_bslash(c))
  280.             return;
  281.         break;
  282.     case CONTROL:
  283.         if (rep_control(c))
  284.             return;
  285.         break;
  286.     case ALLREPS:
  287.         if (rep_bslash(c) || rep_control(c))
  288.             return;
  289.         break;
  290.     case NUMERIC:
  291.         break;
  292.     }
  293.     rep_numeric(c, base);
  294. }
  295.  
  296.  
  297. /*
  298. * rep_bslash - Represent a non-printable char if possible using its
  299. * C Language backslash construct, else return false. '\0' is not included.
  300. */
  301.  
  302. BOOL rep_bslash(c)
  303. short c;
  304. {
  305.     switch (c) {
  306.     case '\n':    putchar('\\');    putchar('n');        break;
  307.     case '\t':    putchar('\\');    putchar('t');        break;
  308.     case '\b':    putchar('\\');    putchar('b');        break;
  309.     case '\r':    putchar('\\');    putchar('r');        break;
  310.     case '\f':    putchar('\\');    putchar('f');        break;
  311.     default  : 
  312.         return (FALSE);
  313.     }
  314.     return (TRUE);
  315. }
  316.  
  317.  
  318. /*
  319. * rep_control -- represent a non-printable char if possible using its
  320. * control character representation, else return false. All non-printing
  321. * ascii chars are representable as control chars (with DEL arbitrarily
  322. * assigned the representation ^?). Characters rejected are those outside
  323. * the range of ascii (ie, left most bit on).
  324. */
  325.  
  326. BOOL rep_control(c)
  327. short c;
  328. {
  329.     if (c < '\0' || c > '\177')
  330.         return (FALSE);
  331.  
  332.     putchar('^');
  333.  
  334.     switch (c) {
  335.     case DEL:
  336.         putchar('?');
  337.         break;
  338.     default:
  339.         putchar(c | 0x40);
  340.         break;
  341.     }
  342.     return (TRUE);
  343. }
  344.  
  345.  
  346. /*
  347. * rep_numeric - Unconditionally represent a character as a numeric value
  348. * using the number base specified.
  349. */
  350.  
  351. rep_numeric(c, base)
  352. short c, base;
  353. {
  354.     char buf[4];
  355.  
  356.     switch (base) {
  357.     case OCT:
  358.         printf("\\%03o", c);
  359.         break;
  360.     case HEX:
  361.         sprintf(buf, "\\%02x\0", c);    /* make it upper case, %X    */
  362.         if (buf[1] >= 'a')                /* doesn't seem to work on    */
  363.             buf[1] &= 0x5F;                /* my compiler.                */
  364.         if (buf[2] >= 'a')
  365.             buf[2] &= 0x5F;
  366.         printf("%s", buf);
  367.         break;
  368.     case DEC:
  369.         printf("\\%03d", c);
  370.         break;
  371.     }
  372. }
  373.  
  374.